package cn.hinglo.common.interceptors.base;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;


/**
 * @author HingLo
 * @createTime: 2018/5/22
 * @description: 所有拦截的父类
 */
public abstract class BaseInterceptor implements Interceptor {

    private static final String OPTIONS = "OPTIONS";

    @Override
    public void intercept(Invocation inv) {
        //获取controller对象
        Controller controller = inv.getController();
        //获取response对象
        HttpServletResponse response = controller.getResponse();
        HttpServletRequest request = controller.getRequest();
        // 若果是option请求，就直接返回响应了
        if (OPTIONS.equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            // 判断是否有指定的忽略注解
            if (isAnnotation(inv.getMethod(), controller)) {
                inv.invoke();
            } else {
                // 具体拦截业务
                this.preHandle(request, response, inv);
            }
        }


    }

    /**
     * 检测是否有指定的忽略注解,如果有指定的忽略注解,就不执行拦截器
     *
     * @param handlerMethod handlerMethod
     * @param controller    controller
     * @return 返回结果,
     */
    private boolean isAnnotation(Method handlerMethod, Controller controller) {
        if (this.ignoreAnnotation() == null) {
            return false;
        }
        return handlerMethod.getAnnotation(ignoreAnnotation()) != null || controller.getClass().getAnnotation(ignoreAnnotation()) != null;
    }

    /***
     * 子类返回忽略的注解
     * @return 返回湖绿注解
     */
    public abstract Class<? extends Annotation> ignoreAnnotation();

    /***
     * 拦截器具体的实现方法
     *
     * @param request 请求对象
     * @param response 响应流对象
     * @param inv inv
     * @return 是否通过
     * @throws Exception ex
     */
    public abstract void preHandle(HttpServletRequest request, HttpServletResponse response, Invocation inv);


}
